﻿module et {
    export class UnOrderMultiMap<T, K>
    {
        private readonly dictionary: Map<T, Array<K>> = new Map<T, Array<K>>();

        // 重用list
        private readonly queue: Array<Array<K>> = new Array<Array<K>>();

        public GetDictionary(): Map<T, Array<K>> {
            return this.dictionary;
        }

        public add(t: T, k: K) {
            let list: Array<K>;
            if (!this.dictionary.has(t)) {
                list = this.fetchList();
                this.dictionary.set(t, list);
            }
            else {
                list = this.dictionary.get(t);
            }
            list.Add(k);
        }

        public first() {
            let kvs=Array.from(this.dictionary);
            return kvs[0];
        }

        public get count() {
            return this.dictionary.size;
        }

        private fetchList(): Array<K> {
            if (this.queue.length > 0) {
                let list = this.queue.shift();
                list.length=0;
                return list;
            }
            return new Array<K>();
        }

        private recycleList(list: Array<K>): void {
            // 防止暴涨
            if (this.queue.length > 100) {
                return;
            }
            list.length=0;
            this.queue.unshift(list);
        }
        public remove(t: T): boolean;
        public remove(t: T, k: K): boolean;
        public remove(t: T, k?: K): boolean {
            if (k != null) {
                let list = this.dictionary.get(t);
                if (list == null) {
                    return false;
                }
                if (!list.Remove(k)) {
                    return false;
                }
                if (list.length == 0) {
                    this.recycleList(list);
                    this.dictionary.delete(t);
                }
                return true;
            }
            else {
                let list = this.dictionary.get(t);
                if (list != null) {
                    this.recycleList(list);
                    this.dictionary.delete(t);
                    return true;
                }
                else {
                    return false;
                }
            }
        }

        /// <summary>
        /// 不返回内部的list,copy一份出来
        /// </summary>
        /// <param name="t"></param>
        /// <returns></returns>
        public getAll(t: T): K[] {
            let list = this.dictionary.get(t);
            if (list == null) {
                return new Array<K>();
            }
            return list;
        }

        /// <summary>
        /// 返回内部的list
        /// </summary>
        /// <param name="t"></param>
        /// <returns></returns>
        public get(t: T): Array<K> {
            return this.dictionary.get(t);
        }

        public getOne(t: T): K {
            let list = this.dictionary.get(t);
            if (list != null && list.length > 0) {
                return list[0];
            }
            return null;
        }

        public contains(t: T, k: K): boolean {
            let list = this.dictionary.get(t);
            if (list == null) {
                return false;
            }
            return list.Contains(k);
        }

        public containsKey(t: T): boolean {
            return this.dictionary.has(t);
        }

        public clear(): void {
            for (let keyValuePair of this.dictionary) {
                this.recycleList(keyValuePair[1]);
            }
            this.dictionary.clear();
        }
    }
    export class UnOrderMultiMapSet<T, K>
    {
        private readonly dictionary: Map<T, Set<K>> = new Map<T, Set<K>>();

        // 重用list
        private readonly queue: Array<Set<K>> = new Array<Set<K>>();

        public GetDictionary(): Map<T, Set<K>> {
            return this.dictionary;
        }

        public add(t: T, k: K) {
            let list: Set<K>;
            if (!this.dictionary.has(t)) {
                list = this.fetchList();
                this.dictionary.set(t, list);
            }
            else {
                list = this.dictionary.get(t);
            }
            list.add(k);
        }

        public first() {
            let kvs=Array.from(this.dictionary);
            return kvs[0];
        }

        public get count() {
            return this.dictionary.size;
        }

        private fetchList(): Set<K> {
            if (this.queue.length > 0) {
                let list = this.queue.shift();
                list.clear();
                return list;
            }
            return new Set<K>();
        }

        private recycleList(list: Set<K>): void {
            // 防止暴涨
            if (this.queue.length > 100) {
                return;
            }
            list.clear();
            this.queue.unshift(list);
        }
        public remove(t: T): boolean;
        public remove(t: T, k: K): boolean;
        public remove(t: T, k?: K): boolean {
            if (k != null) {
                let list = this.dictionary.get(t);
                if (list == null) {
                    return false;
                }
                if (!list.delete(k)) {
                    return false;
                }
                if (list.size == 0) {
                    this.recycleList(list);
                    this.dictionary.delete(t);
                }
                return true;
            }
            else {
                let list = this.dictionary.get(t);
                if (list != null) {
                    this.recycleList(list);
                    this.dictionary.delete(t);
                    return true;
                }
                else {
                    return false;
                }
            }
        }

        /// <summary>
        /// 不返回内部的list,copy一份出来
        /// </summary>
        /// <param name="t"></param>
        /// <returns></returns>
        public getAll(t: T) {
            let list = this.dictionary.get(t);
            if (list == null) {
                return new Set<T>();
            }
            return Array.from(list.values());
        }

        /// <summary>
        /// 返回内部的list
        /// </summary>
        /// <param name="t"></param>
        /// <returns></returns>
        public get(t: T): Set<K> {
            return this.dictionary.get(t);
        }

        public getOne(t: T): K {
            let list = this.dictionary.get(t);
            if (list != null && list.size > 0) {
                return list[0];
            }
            return null;
        }

        public contains(t: T, k: K): boolean {
            let list = this.dictionary.get(t);
            if (list == null) {
                return false;
            }
            return list.has(k);
        }

        public containsKey(t: T): boolean {
            return this.dictionary.has(t);
        }

        public clear(): void {
            for (let keyValuePair of this.dictionary) {
                this.recycleList(keyValuePair[1]);
            }
            this.dictionary.clear();
        }
    }
}
